﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace ITSP_Instance_Generator
{
    public partial class Form1 : Form
    {
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.Text = @"[10, 11, 20, 30, 40, 41, 50]
845
10626
[1, 1, 2, 3, 4, 4, 5]
[[0, 0, 473, 120, 636, 636, 366],
[0, 0, 473, 120, 636, 636, 366],
[473, 473, 0, 359, 201, 201, 184],
[120, 120, 359, 0, 516, 516, 246],
[636, 636, 201, 516, 0, 0, 280],
[636, 636, 201, 516, 0, 0, 280],
[366, 366, 184, 246, 280, 280, 0]]";
        }

        private String[] textArrayToStringArray(String input)
        {
            return Regex.Split(input.Substring(1, input.Length - 2), ", ");
        }

        private double[][] textMatrixToDoubleMatrix(String[] input)
        {
            double[][] retMatrix = new double[input.Length][];
            for (int i = 0; i < input.Length; i++)
            {

                retMatrix[i] = new double[input.Length];
                String[] arrayElements = 
                    input[i]
                    .Replace("[", "")
                    .Replace("]", "")
                    .Replace(",", "")
                    .Split(' ');
                for (int j = 0; j < input.Length; j++)
                    retMatrix[i][j] = Double.Parse(arrayElements[j]);
            }
            return retMatrix;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            String[] lines = Regex.Split(textBox1.Text, "\r\n|\r|\n");
            String bound = lines[1];
            // ignore lines[2]
            String[] nodeLabels = textArrayToStringArray(lines[3]);

            String[] matrix = new string[lines.Length - 4];
            for (int i = 4; i < matrix.Length+4; i++)
                matrix[i-4] = lines[i];
            double[][] distanceMatrix = textMatrixToDoubleMatrix(matrix);

            var nodeList = new List<Node>();
            foreach (String n in nodeLabels)
            {
                int i = Int32.Parse(n);
                if (nodeList.Count > 0)
                {
                    Node lastNode = nodeList.Last();
                    if (lastNode.Number == i)
                        lastNode.NumberOfVisits++;
                    else
                        nodeList.Add(new Node(i,1));
                }
                else
                {
                    nodeList.Add(new Node(i, 1));
                }
            }
            Instance test = new Instance(nodeList.ToArray(), Int32.Parse(bound), distanceMatrix);
            textBox2.Text = test.ToZIMPL();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Generator g = new Generator(5, 1000, 1000, 2, 3, 800, 1200);
            Instance i = g.Generate();
            textBox2.Text = i.ToZIMPL();

        }

        private void button3_Click(object sender, EventArgs e)
        {
            SA_Instance SAI = new SA_Instance(new Generator(5, 1000, 1000, 1, 3, 1000, 25).Generate());
            int x = 3;
            SAI.GenerateNextMove();
            SAI.GenerateNextMove();
            SAI.GenerateNextMove();
            SAI.GenerateNextMove();
            SAI.GenerateNextMove();
            x = 4;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            List<IGenerator> test = new List<IGenerator>();
            /*
            int[] problemSizes = new int[]{6, 8, 10};
            int[] bounds = new int[]{500, 1000, 1500, 2000, 2500};
            int boundDelta = 25;
            int[] maxVisits = new int[]{2,3,5};*/
            int[] problemSizes = new int[] { 10 };
            //int[] bounds = new int[] { 500, 1000, 1500, 2000, 2500 };
            int boundDelta = 25;
            int[] maxVisits = new int[] { 2, 3, 4, 5 };
            foreach(int probSize in problemSizes)
                    foreach(int maxV in maxVisits)
                    {
                        for (int bound = 50; bound <= 1000; bound += 100)
                        {
                            IGenerator g = new Generator(probSize, 1000, 1000, 1, maxV, bound, boundDelta);
                            test.Add(g);
                        }
                    }
            Experiment exp = new Experiment(test, 10);
            exp.Run();
            /*
            for(int problem)
            for(int bound = 500; bound <= 2000; bound += 500)
            for (int maxVisits = 1; maxVisits <= 4; maxVisits++)
            {
                IGenerator g = new Generator(4, 1000, 1000, 1, maxVisits, bound-5, bound+5);
                test.Add(g);
            }
            Experiment exp = new Experiment(test, 10);
            textBox2.Text = exp.Run();*/
        }

        public static void CreateAverages()
        {
            if (Directory.Exists("experiments\\runs"))
            {
                foreach(String d in Directory.EnumerateDirectories("experiments/runs"))
                {
                    String summaryFileName = d + "\\summary.txt";
                    File.Create(summaryFileName).Dispose();
                    StreamWriter w = File.AppendText(summaryFileName);
                    foreach (String f in Directory.EnumerateFiles(d))
                    {
                        if (f != summaryFileName)
                        {
                            StreamReader file = new StreamReader(f);
                            String line;
                            int counter = 0;
                            long sum = 0;
                            while ((line = file.ReadLine()) != null)
                            {
                                long l;
                                if (long.TryParse(line, out l))
                                {
                                    sum += l;
                                    counter++;
                                }
                            }
                            double average = (double) sum/counter;
                            w.WriteLine(f.Replace(';','\t').Replace(".txt","").Replace("experiments/runs\\", "") + "\t" + counter  + "\t" + average);
                            file.Close();
                        }
                    }
                    w.Close();
                }
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            CreateAverages();
        }

        private Experiment ex;
        private void button6_Click(object sender, EventArgs e)
        {
            IGenerator test = new GeneratorTSPLIB("a280.tsp", 1, 3, 100, 500);
            ex = new Experiment(test, 10);
            ex.Run();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if(ex != null)
                ex.Close();
        }

        private void button7_Click(object sender, EventArgs e)
        {
            var a = new Generator(18, 1000, 1000, 1, 1, 0, 0);
            /*SA_Instance testSA = new SA_Instance(a.Generate());
            var oldSAI = testSA;
            double averageDelta = 0;
            for (int i = 0; i < 1000000; i++)
            {
                var nextSAI = oldSAI.GenerateNextMove();
                averageDelta += (nextSAI.TourCost - oldSAI.TourCost) / 1000000;
                oldSAI = nextSAI;
            }
            MessageBox.Show("" + averageDelta + "  " + averageDelta*1000000);*/
            SA sa = new SA(a.Generate());
            sa.Run();
            MessageBox.Show("" + sa.bestFoundTourCostTestVar + "nrIts" + sa.nrIts);
        }

    }
}
